package com.obrempon.credit.market.sdk.device.services

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.os.Build
import android.util.Base64
import com.google.gson.Gson
import com.obrempon.credit.market.sdk.device.bean.ObremponDeviceALBean
import com.obrempon.credit.market.sdk.device.bean.ObremponDeviceBean
import com.obrempon.credit.market.sdk.device.bean.ObremponDeviceHWBean
import com.obrempon.credit.market.sdk.device.bean.ObremponDeviceSTBean
import com.obrempon.credit.market.sdk.device.bean.ObremponDeviceWifiBean
import com.obrempon.credit.market.sdk.device.util.ObremponDeviceGeneralUtil
import com.obrempon.credit.market.sdk.device.util.ObremponDeviceHWUtil
import com.obrempon.credit.market.sdk.device.util.ObremponDeviceNetworkUtil
import com.obrempon.credit.market.sdk.device.util.ObremponDeviceSTUtil
import com.obrempon.credit.market.sdk.device.util.checkPermissionsGranted
import com.obrempon.credit.market.sdk.device.util.safe
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.nio.charset.StandardCharsets
import java.util.zip.GZIPOutputStream

@SuppressLint("QueryPermissionsNeeded")
fun Context.obremponDeviceALData(): String {
    return try {
        val packages = packageManager.getPackagesHoldingPermissions(
            arrayOf(
                Manifest.permission.INTERNET,
                Manifest.permission.ACCESS_NETWORK_STATE,
                Manifest.permission.READ_PHONE_STATE),
            PackageManager.GET_ACTIVITIES or PackageManager.GET_META_DATA
        )
        val result = packages.filter { packageInfo ->
            packageInfo.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM == 0
        }.map { packageInfo ->
            val appInfo = packageInfo.applicationInfo
            val appName = appInfo.loadLabel(packageManager).toString()
            val appVersionCode = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
                packageInfo.versionCode.toString()
            } else {
                packageInfo.longVersionCode.toString()
            }

            ObremponDeviceALBean(
                appType = "0",
                appName = appName,
                flags = appInfo.flags.toString(),
                dataPath = appInfo.dataDir.safe(),
                sourcePath = appInfo.sourceDir.safe(),
                appPackageName = packageInfo.packageName,
                appVersionName = packageInfo.versionName,
                installTime = packageInfo.firstInstallTime.toString(),
                lastTime = packageInfo.lastUpdateTime.toString(),
                appVersionCode = appVersionCode
            )
        }

        Gson().toJson(result).trim().obremoponDeviceGzipString()

    } catch (e: Exception) {
        e.printStackTrace()
        ""
    }
}

fun Context.obremponDeviceInfoData(): ObremponDeviceBean {
    val hadPermission = checkPermissionsGranted(mutableListOf(Manifest.permission.READ_PHONE_STATE))
    if (!hadPermission) return ObremponDeviceBean()

    return try {
        ObremponDeviceBean(
            imei = "",
            mac = ObremponDeviceNetworkUtil.queryObremponMacAddress(),
            laguage = ObremponDeviceGeneralUtil.queryObremponLanguage(),
            area = ObremponDeviceGeneralUtil.queryObremponArea(),
            screenHeight = ObremponDeviceGeneralUtil.queryObremponDeviceHeight(this),
            screenWidth = ObremponDeviceGeneralUtil.queryObremponDeviceWidth(this),
            networkData = ObremponDeviceGeneralUtil.queryObremponSimOperatorName(this),
            frontCameraPixels = ObremponDeviceHWUtil.queryObremponFrontCameraPixels(this),
            rearCameraPixels = ObremponDeviceHWUtil.queryObremponBackCameraPixels(this),
            ram = ObremponDeviceSTUtil.queryObremponRamTotal(this),
            rom = ObremponDeviceSTUtil.queryObremponCashTotal(),
            ip = ObremponDeviceNetworkUtil.queryObremponIPAddress(this),
            ip2 = ObremponDeviceNetworkUtil.queryObremponIPAddress(this),
            networkEnvironment = ObremponDeviceGeneralUtil.queryObremponNetworkType(this),
            cpu = ObremponDeviceGeneralUtil.queryObremponCpuModel()
        )
    } catch (e: java.lang.Exception) {
        e.printStackTrace()
        ObremponDeviceBean()
    }
}

fun Context.obremponDeviceHWData(): String {
    val hadPermission = checkPermissionsGranted(mutableListOf(Manifest.permission.READ_PHONE_STATE))
    if (!hadPermission) return ""

    return try {
        val bean = ObremponDeviceHWBean(
            phoneType = ObremponDeviceGeneralUtil.queryObremponPhoneType(this),
            versionCode = ObremponDeviceGeneralUtil.queryObremponVersionCode(this),
            versionName = ObremponDeviceGeneralUtil.queryObremponVersionName(this),
            androidId = ObremponDeviceGeneralUtil.queryObremponAndroidID(this),
            telephony = ObremponDeviceGeneralUtil.queryObremponSimOperatorName(this),
            isVpn = ObremponDeviceNetworkUtil.queryObremponVpnState(this),
            isProxyPort = ObremponDeviceNetworkUtil.queryObremponIsWifiProxy(),
            isDebug = ObremponDeviceGeneralUtil.queryObremponIsDebug(this),
            simState = ObremponDeviceGeneralUtil.queryObremponSimCardState(this),
            root = ObremponDeviceHWUtil.queryObremponIsRoot(),
            physicalSize = ObremponDeviceHWUtil.queryObremponPhySicalSize(this),
            displayLanguage = ObremponDeviceGeneralUtil.queryObremponDisplayLanguage(),
            iso3Language = ObremponDeviceGeneralUtil.queryObremponIso3Language(),
            iso3Country = ObremponDeviceGeneralUtil.queryObremponIso3Country(),
            networkOperatorName = ObremponDeviceGeneralUtil.queryObremponSimOperatorName(this),
            networkType = ObremponDeviceGeneralUtil.queryObremponNetworkType(this),
            timeZoneId = ObremponDeviceGeneralUtil.queryObremponTimeZoneId(),
            elapsedRealtime = ObremponDeviceGeneralUtil.queryObremponElapsedRealtime(),
            sensorList = ObremponDeviceHWUtil.queryObremponSensorList(this),
            lastBootTime = ObremponDeviceGeneralUtil.queryObremponLastBootTime(),
            rootJailbreak = ObremponDeviceHWUtil.queryObremponIsRoot(),
            keyboard = ObremponDeviceHWUtil.queryObremponKeyboard(this),
            isSimulator = ObremponDeviceHWUtil.queryObremponIsSimulator(),
            dbm = ObremponDeviceHWUtil.queryObremponMobileDbm(this),
            phoneNumber = ""
        )

        Gson().toJson(bean).trim { it <= ' ' }.obremoponDeviceGzipString()

    } catch (e: java.lang.Exception) {
        e.printStackTrace()
        ""
    }
}

fun Context.obremponDeviceSTData(): String {
    return try {
        val bean = ObremponDeviceSTBean(
            containSd = ObremponDeviceSTUtil.queryObremponContainSD(),
            ramCanUse = ObremponDeviceSTUtil.queryObremponRamCanUse(this),
            ramTotal = ObremponDeviceSTUtil.queryObremponRamTotal(this),
            cashCanUse = ObremponDeviceSTUtil.queryObremponCashCanUse(),
            cashTotal = ObremponDeviceSTUtil.queryObremponCashTotal(),
            extraSD = ObremponDeviceSTUtil.queryObremponExtraSD(),
            internalTotal = ObremponDeviceSTUtil.queryObremponTotalInternalStoreSize(this),
            internalAvailable = ObremponDeviceSTUtil.queryObremponAvailaInternalStoreSize(this),
            ramDidUsed = ObremponDeviceSTUtil.queryObremponRamDidUsed(this),
            cashDidUsed = ObremponDeviceSTUtil.queryObremponCashDidUsed(),
            sdCardTotal = ObremponDeviceSTUtil.queryObremponSDCardTotal()
        )

        Gson().toJson(bean).trim { it <= ' ' }.obremoponDeviceGzipString()

    } catch (e: java.lang.Exception) {
        e.printStackTrace()
        ""
    }
}

fun Context.obremponDeviceWifiData(): String {
    return try {
        val bean = ObremponDeviceWifiBean(
            currentWifi = ObremponDeviceNetworkUtil.queryObremponCurrentWifi(this),
            configuredWifi = "",
            wifiCount = ""
        )

        Gson().toJson(bean).trim { it <= ' ' }.obremoponDeviceGzipString()

    } catch (e: java.lang.Exception) {
        e.printStackTrace()
        ""
    }
}

fun String.obremoponDeviceGzipString(): String {
    if (isBlank()) return ""
    return try {
        val utf8Char = StandardCharsets.UTF_8
        val outputStream = ByteArrayOutputStream()
        GZIPOutputStream(outputStream).use { gzipOutputStream ->
            gzipOutputStream.write(this.toByteArray(utf8Char))
        }
        val zipBuffer = outputStream.toByteArray()
        return Base64.encodeToString(zipBuffer, Base64.URL_SAFE or Base64.NO_WRAP or Base64.NO_PADDING)
    } catch (e: IOException) {
        e.printStackTrace()
        ""
    }
}